package com.pureut.scheduling.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.datascope.annotation.DataScope;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.production.api.FeignProductionService;
import com.pureut.scheduling.domain.BackWeight;
import com.pureut.scheduling.domain.SchedulingPlan;
import com.pureut.scheduling.domain.SchedulingPlan2;
import com.pureut.scheduling.domain.SchedulingProduction;
import com.pureut.scheduling.domain.dto.SchedulingOrderDto;
import com.pureut.scheduling.domain.dto.SchedulingPlanDto;
import com.pureut.scheduling.domain.dto.SchedulingProductionDto;
import com.pureut.scheduling.domain.vo.MaterialMqVo;
import com.pureut.scheduling.domain.vo.SchedulingPlanVo;
import com.pureut.scheduling.domain.vo.UpdateSaleVo;
import com.pureut.scheduling.mapper.SchedulingPlan2Mapper;
import com.pureut.scheduling.mapper.SchedulingPlanMapper;
import com.pureut.scheduling.mapper.SchedulingProductionMapper;
import com.pureut.scheduling.service.ISchedulingPlan2Service;
import com.pureut.scheduling.service.ISchedulingPlanService;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.OrderFeignService;
import com.pureut.system.api.domain.SysDictData;
import com.pureut.system.api.vo.BackDataVo;
import com.pureut.system.api.vo.SalesOrderDetailVo;
import com.pureut.system.api.vo.UpdateSaleOrderDetailStatusVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description 排程计划实现类
 * @Date 22-12-16
 * @Author hl
 **/
@Service
public class SchedulingPlanServiceImpl extends ServiceImpl<SchedulingPlanMapper, SchedulingPlan> implements ISchedulingPlanService {

    @Resource
    private SchedulingPlanMapper schedulingPlanMapper;

    @Resource
    private FeignService feignService;

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private SchedulingProductionMapper schedulingProductionMapper;

    @Resource
    FeignProductionService feignProductionService;


    /**
     * 查询计划排程信息
     *
     * @param schedulingPlanVo 排程信息接受类
     * @return list 排程集合
     */
    @Override
    @DataScope(deptAlias = "scheduling_plan")
    public List<SchedulingPlanDto> selectPlanList(SchedulingPlanVo schedulingPlanVo) {
        List<SysDictData> netArray = DictUtils.getDictCache("scheduling_plan_state");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        List<SchedulingPlanDto> list = schedulingPlanMapper.selectPlanList(schedulingPlanVo);
        for (SchedulingPlanDto dto :
                list) {
            dto.setPlanStateDict(netMap.get(dto.getPlanState()));
        }
        return list;
    }

    /**
     * 确认排程计划信息
     *
     * @param schedulingPlanVo 排程信息接受类
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSchedulingPlan(SchedulingPlanVo schedulingPlanVo) throws Exception {
        schedulingPlanVo.setPlanState(2);
        schedulingPlanVo.setOperatorBy(SecurityUtils.getUsername());
        int ins = schedulingPlanMapper.updateSchedulingPlan(schedulingPlanVo);
        if (ins == 0) {
            throw new SQLException("撤回失败");
        }
        SchedulingProduction production = new SchedulingProduction();
        String[] codeS = schedulingPlanVo.getPlanAssociatedCode().split("-");
        production.setPlanId(schedulingPlanVo.getPlanId());
        String cStr = "YP-" + codeS[1];
        int max = schedulingProductionMapper.maxSchedulingProduct(cStr);
        max += 1;
        String qw = "";
        if (max < 10) {
            qw = "0" + max;
        } else {
            qw = String.valueOf(max);
        }
        production.setProductionCode(cStr + "-" + qw);
        production.setProductionState(1);
        return schedulingProductionMapper.insertSchedulingProduct(production);
    }

    /**
     * 退回排程计划
     *
     * @param schedulingPlan 计划实体类
     * @return 1 成功 0 失败
     */
    @Override
    public int updatePlanBackEdit(SchedulingPlan schedulingPlan) {
        int i = schedulingPlanMapper.updatePlanBackEdit(schedulingPlan);
        //获取排程计划数据
        SchedulingOrderDto schedulingOrderDto = schedulingPlanMapper.selectPlanOnById(schedulingPlan.getPlanId());
        UpdateSaleOrderDetailStatusVo updateSaleOrderDetailStatusVo = new UpdateSaleOrderDetailStatusVo();
        updateSaleOrderDetailStatusVo.setMaterialCode(schedulingOrderDto.getPlanMaterialCode());
        updateSaleOrderDetailStatusVo.setSaleOrderNo(schedulingOrderDto.getPlanAssociatedCode());
        updateSaleOrderDetailStatusVo.setStatus(7);
        orderFeignService.updateSaleOrderDetailStatus(updateSaleOrderDetailStatusVo);
        return i;
    }

    /**
     * 退回排程终止
     *
     * @param schedulingPlan 计划实体类
     * @return 1 成功 0 失败
     */
    @Override
    public int updatePlanTheEndEdit(SchedulingPlan schedulingPlan) {
        SchedulingOrderDto schedulingOrderDto = schedulingPlanMapper.selectPlanOnById(schedulingPlan.getPlanId());
        if ("2".equals(schedulingOrderDto.getPlanState()) || "3".equals(schedulingOrderDto.getPlanState())) {
            //对“生产中”的单据进行终止时，校验此计划关联的全部水刺制令单状态是否为“已完成/已关结”，是则终止成功，否则提示“此计划存在未关结制令单，请生产完成再终止”
            if ("3".equals(schedulingOrderDto.getPlanState())) {
                String planNumber = schedulingOrderDto.getPlanCode();
                boolean statusByPlanNumber = feignProductionService.getStatusByPlanNumber(planNumber);
                if (statusByPlanNumber) {
                    schedulingPlan.setOperatorBy(SecurityUtils.getUsername());
                    int i = schedulingPlanMapper.updatePlanTheEndEdit(schedulingPlan);
                    //获取排程计划数据
                    UpdateSaleOrderDetailStatusVo updateSaleOrderDetailStatusVo = new UpdateSaleOrderDetailStatusVo();
                    updateSaleOrderDetailStatusVo.setMaterialCode(schedulingOrderDto.getPlanMaterialCode());
                    updateSaleOrderDetailStatusVo.setSaleOrderNo(schedulingOrderDto.getPlanAssociatedCode());
                    updateSaleOrderDetailStatusVo.setStatus(6);
                    orderFeignService.updateSaleOrderDetailStatus(updateSaleOrderDetailStatusVo);
                    return i;
                } else {
                    throw new GlobalException("此计划存在未关结制令单，请生产完成再终止");
                }
            } else {
                int i = schedulingPlanMapper.updatePlanTheEndEdit(schedulingPlan);
                //获取排程计划数据
                UpdateSaleOrderDetailStatusVo updateSaleOrderDetailStatusVo = new UpdateSaleOrderDetailStatusVo();
                updateSaleOrderDetailStatusVo.setMaterialCode(schedulingOrderDto.getPlanMaterialCode());
                updateSaleOrderDetailStatusVo.setSaleOrderNo(schedulingOrderDto.getPlanAssociatedCode());
                updateSaleOrderDetailStatusVo.setStatus(6);
                orderFeignService.updateSaleOrderDetailStatus(updateSaleOrderDetailStatusVo);

                //删除预排程单
                String substring = schedulingOrderDto.getPlanCode().substring(2);
                schedulingPlanMapper.removeProductionScheling(substring);

                return i;
            }
        } else {
            throw new GlobalException("只能对“待排程、生产中”的单据进行终止");
        }
    }

    /**
     * 查询单个计划排程信息(销售or样品)
     *
     * @param planId 计划id
     * @return SchedulingPlanDto 计划排程返回类
     */
    @Override
    public SchedulingOrderDto selectSchedulingPlanById(long planId) {
        SchedulingOrderDto schedulingOrderDto = schedulingPlanMapper.selectPlanOnById(planId);
        List<SysDictData> netArray = DictUtils.getDictCache("sys_type_net");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        schedulingOrderDto.setMaterialNetTypeDict(netMap.get(String.valueOf(schedulingOrderDto.getMaterialNet())));
        List<SysDictData> netOfArray = DictUtils.getDictCache("sys_of_type");
        Map<String, String> netOfMap = netOfArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        schedulingOrderDto.setMaterialNetDict(netOfMap.get(String.valueOf(schedulingOrderDto.getMaterialNetType())));
        List<SysDictData> netArray3 = DictUtils.getDictCache("sale_order_packing");
        Map<String, String> netMap3 = netArray3.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        schedulingOrderDto.setPackingDict(netMap3.get(String.valueOf(schedulingOrderDto.getPacking())));
        return schedulingOrderDto;
    }


    /**
     * 排程计划新增
     *
     * @param planList 计划实体类
     * @return 1 成功 0 失败
     */
    @Override
    public int insertSchedulingOrderPlan(List<SchedulingPlanVo> planList) {
        String userName = SecurityUtils.getUsername();
        long deptId = SecurityUtils.getDeptId();
        for (int i = 0; i < planList.size(); i++) {
            SchedulingPlanVo vo = planList.get(i);
            vo.setDeptId(deptId);
            String[] codeS = vo.getPlanAssociatedCode().split("-");
            if (i == 0) {
                vo.setPlanCode("SJ-" + codeS[1]);
            } else {
                vo.setPlanCode("SJ-" + codeS[1] + "S-" + i);
            }
            vo.setCreateBy(userName);
        }
        return schedulingPlanMapper.insertSchedulingOrderPlan(planList);
    }

    /**
     * 回传重量
     *
     * @param backWeight 回传实体类
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updatePlanBack(BackWeight backWeight) {
        double we = backWeight.getProductionOutputWeight();
        double subcontractWeight = backWeight.getSubcontractWeight();
        if (we > 0 || subcontractWeight > 0) {
            schedulingPlanMapper.updatePlanBack(backWeight);
        }
        int kl = schedulingProductionMapper.updateBackWeight(backWeight);
        if (subcontractWeight > 0) {
            //修改之后判断单据状态,更改为：产出重量+委外入库重量>=计划重量，单据为“已完成”状态
            String planCode = backWeight.getPlanCode();
            //获取生产计划单据
            SchedulingPlanDto planView = schedulingPlanMapper.getPlanView(planCode);
            //获取生产排程单据
            SchedulingProductionDto productionView = schedulingProductionMapper.getProductionView(planView.getPlanId());
            //产出重量
            double productionOutputWeight = productionView.getProductionOutputWeight();
            //委外入库重量
            double subcontractWeightProduction = productionView.getSubcontractWeight();
            //计划重量
            double planContractWeight = productionView.getPlanContractWeight();
            BigDecimal add = new BigDecimal(String.valueOf(productionOutputWeight)).add(new BigDecimal(String.valueOf(subcontractWeightProduction)));
            double v = Double.parseDouble(add.toString());
            /*
            if (Double.doubleToLongBits(v) >= Double.doubleToLongBits(planContractWeight)) {
                //修改生产计划状态为已完成
                boolean b = schedulingPlanMapper.updatePlanStatus(planView.getPlanId());
                System.out.println(b);
                //修改生产排程状态为已完成
                boolean b1 = schedulingProductionMapper.updateProductStatus(productionView.getProductionId());
                System.out.println(b1);
            }
            */
            if (backWeight.getMark() == null) {
                //回传销售订单明细相关重量
                BackDataVo backDataVo = new BackDataVo();
                backDataVo.setSaleNumber(planView.getPlanAssociatedCode());
                backDataVo.setMaterialCode(planView.getPlanMaterialCode());
                backDataVo.setNetWeight(subcontractWeight);
                boolean b = orderFeignService.updateSubWeight(backDataVo);
                System.out.println(b);
            }
        }
        return kl;
    }

    /**
     * 分切完成关结且水刺关结完成修改排程单和计划单状态为已完成
     *
     * @return 1 成功 0 失败
     */
    @Override
    public int updatePlanFinishStatus(BackWeight backWeight) {
        //修改之后判断单据状态,更改为：产出重量+委外入库重量>=计划重量，单据为“已完成”状态
        String planCodes = backWeight.getPlanCode();

        String[] split = planCodes.split(",");

        int update = 0;

        for (String planCode : split) {

            update = 0;

            //获取生产计划单据
            SchedulingPlanDto planView = schedulingPlanMapper.getPlanView(planCode);
            //获取生产排程单据
            SchedulingProductionDto productionView = schedulingProductionMapper.getProductionView(planView.getPlanId());
            //产出重量
            double productionOutputWeight = productionView.getProductionOutputWeight();
            //委外入库重量
            double subcontractWeightProduction = productionView.getSubcontractWeight();
            //计划重量
            double planContractWeight = productionView.getPlanContractWeight();
            BigDecimal add = new BigDecimal(String.valueOf(productionOutputWeight)).add(new BigDecimal(String.valueOf(subcontractWeightProduction)));
            double v = Double.parseDouble(add.toString());

            if (Double.doubleToLongBits(v) >= Double.doubleToLongBits(planContractWeight)) {
                //修改生产计划状态为已完成
                boolean b = schedulingPlanMapper.updatePlanStatus(planView.getPlanId());

                if (b) {
                    //修改生产排程状态为已完成
                    schedulingProductionMapper.updateProductStatus(productionView.getProductionId());
                    //修改销售订单明细状态为已完成
                    BackDataVo backDataVo = new BackDataVo();
                    backDataVo.setStatus("8");
                    backDataVo.setMaterialCode(planView.getPlanMaterialCode());
                    backDataVo.setSaleNumber(planView.getPlanAssociatedCode());
                    orderFeignService.updateSaleStatus(backDataVo);
                    update = 1;
                }

            }
        }


        return update;
    }

    /**
     * 通过计划单号获取对应销售订单号(fegin调用)
     *
     * @param planCode
     * @return
     */
    @Override
    public String getPlanData(String planCode) {
        return schedulingPlanMapper.getPlanData(planCode);
    }

    /**
     * 查询排程计划信息(状态为“待排产、生产中”的单据)
     *
     * @return
     */
    @Override
    public List<SchedulingPlanDto> getListByStatus() {

        return schedulingPlanMapper.getListByStatus();
    }

    /**
     * 物料同步
     *
     * @param mq mq接受类
     */
    public void updatePlanMaterialFinished(MaterialMqVo mq) {
        schedulingPlanMapper.updatePlanMaterialFinished(mq);
    }

    /**
     * 根据计划单号查出排程计划信息
     *
     * @param planCode
     * @return
     */
    @Override
    public SchedulingPlanDto getPlanInfo(String planCode) {
        return schedulingPlanMapper.getPlanInfo(planCode);
    }

    /**
     * 修改计划排程单状态
     *
     * @param updateSaleVo
     * @return
     */
    @Override
    public boolean updatePlanStatusUnit(UpdateSaleVo updateSaleVo) {

//        schedulingPlanMapper.updatePlanStatusUnit(updateSaleVo);
        SalesOrderDetailVo salesData = updateSaleVo.getSalesData();
//        List<SchedulingPlanDto> schedulingPlan = schedulingPlanMapper.getSchedulingPlan(updateSaleVo);
        //修改排程数据
        boolean b = schedulingPlanMapper.updateSchedulingPlanData(salesData, updateSaleVo);
        return b;
    }

    /**
     * 修改排程委外重量（扣减）
     *
     * @param backWeight
     * @return
     */
    @Override
    public int updatePlanBackDelete(BackWeight backWeight) {
        double we = backWeight.getProductionOutputWeight();
        double subcontractWeight = backWeight.getSubcontractWeight();
        if (we > 0 || subcontractWeight > 0) {
            schedulingPlanMapper.updatePlanBackDelete(backWeight);
        }
        int kl = schedulingProductionMapper.updateBackWeightDelete(backWeight);
        if (subcontractWeight > 0) {
            //修改之后判断单据状态,更改为：产出重量+委外入库重量>=计划重量，单据为“已完成”状态
            String planCode = backWeight.getPlanCode();
            //获取生产计划单据
            SchedulingPlanDto planView = schedulingPlanMapper.getPlanView(planCode);

            //回传销售订单明细相关重量(扣减委外重量)
            BackDataVo backDataVo = new BackDataVo();
            backDataVo.setSaleNumber(planView.getPlanAssociatedCode());
            backDataVo.setMaterialCode(planView.getPlanMaterialCode());
            backDataVo.setNetWeight(subcontractWeight);
            boolean b = orderFeignService.updateSubWeightDelete(backDataVo);
            System.out.println(b);
        }
        return kl;
    }

}

